#include "PreCompiled.h"
#include "Application.h"
#include "Command.h"
#include "MainWindow.h"
#include "WorkbenchManager.h"
#include "Application_App.h"
#include "Document_Gui.h"
#include "viewProviderDocumentObject.h"
#include "Workbench.h"
#include "VIewWindow.h"
#include "View3DInventor.h"
#include "ViewProvider.h"
#include "NavigationStyle.h"
#include "ViewFurniture_staff.h"
#include "PropertyItem.h"
/** Override QCoreApplication::notify() to fetch exceptions in Qt widgets
 * properly that are not handled in the event handler or slot.
 */
using namespace Gui;
using namespace PropertyEditor;
class GUIApplication : public QApplication
{
    int systemExit;
public:
    GUIApplication(int & argc, char ** argv, int exitcode)
        : QApplication(argc, argv), systemExit(exitcode)
    {
    }

    /**
     * Make forwarding events exception-safe and get more detailed information
     * where an unhandled exception comes from.
     */
    bool notify (QObject * receiver, QEvent * event)
    {
        if (!receiver && event) {
//             Base::Console().Log("GUIApplication::notify: Unexpected null receiver, event type: %d\n",
//                 (int)event->type());
        }
        try {
//             if (event->type() == Spaceball::ButtonEvent::ButtonEventType || 
//                 event->type() == Spaceball::MotionEvent::MotionEventType)
//                 return processSpaceballEvent(receiver, event);
//             else
               return  QApplication::notify(receiver, event);
        }
//         catch (const Base::SystemExitException&) {
//             qApp->exit(systemExit);
//             return true;
//         }
//        catch (const Base::Exception& e) {
            //Base::Console().Error("Unhandled Base::Exception caught in GUIApplication::notify.\n"
                                //  "The error message is: %s\n", e.what());
 //       }
 //       catch (const std::exception& e) {
          //  Base::Console().Error("Unhandled std::exception caught in GUIApplication::notify.\n"
                                //  "The error message is: %s\n", e.what());
 //       }
        catch (...) {
           // Base::Console().Error("Unhandled unknown exception caught in GUIApplication::notify.\n");
        }

        // Print some more information to the log file (if active) to ease bug fixing
        if (receiver && event) {
            std::stringstream dump;
            dump << "The event type " << (int)event->type() << " was sent to "
                 << receiver->metaObject()->className() << "\n";
            dump << "Object tree:\n";
            if (receiver->isWidgetType()) {
                QWidget* w = qobject_cast<QWidget*>(receiver);
                while (w) {
                    dump << "\t";
                    dump << w->metaObject()->className();
                    QString name = w->objectName();
                    if (!name.isEmpty())
                        dump << " (" << (const char*)name.toUtf8() << ")";
                    w = w->parentWidget();
                    if (w)
                        dump << " is child of\n";
                }
                std::string str = dump.str();
               // Base::Console().Log("%s",str.c_str());
            }
        }

        return true;
    }
    void commitData(QSessionManager &manager)
    {
        if (manager.allowsInteraction()) {
            if (!getMainWindow()->close()) {
                // cancel the shutdown
                manager.release();
                manager.cancel();
            }
        }
        else {
            // no user interaction allowed, thus close all documents and
            // the main window
            GetApplication().closeAllDocuments();
            getMainWindow()->close();
        }

    }
};




struct ApplicationP
{
	ApplicationP()
		:activeDocument(0),
		isClosing(false),
		startingUp(true)
{
}
   CommandManager commandManager;
   Document_Gui* activeDocument;
   std::map<const Document_App*,Document_Gui*> documents;
   std::list<ViewWindow*> passive;
   bool isClosing;
   bool startingUp;
};

Application* Application::_instance = 0;
Application::Application(void)
{

	GetApplication().signalNewDocument.connect(boost::BOOST_BIND(&Application::slotNewDocument,this,_1));

// 	ParameterGrp::handle hPGrp = GetApplication().GetUserParameter().GetGroup("BaseApp");
// 	hPGrp = hPGrp->GetGroup("Preferences")->GetGroup("General");

	//QString lang = QLocale::languageToString(QLocale::system().language());


// 	ParameterGrp::handle hUnits = GetApplication().GetParameterGroupByPath
// 		("User parameter:BaseApp/Preferences/Units");
// 	Base::UnitsApi::setDecimals(hUnits->GetInt("Decimals", Base::UnitsApi::getDecimals()));


	d = new  ApplicationP;
	_instance = this;

	createStandardOperations();
}

Application::~Application(void)
{
	delete d;
	_instance = 0;
}
void  Application::initTypes()
{
	BaseView                       ::init();
	ViewWindow                     ::init();
	View3DInventor                 ::init();
	Gui::ViewProvider              ::init();

	Gui::ViewProviderDocumentObject              ::init();
	Gui::ViewProviderFurnitureEntityProperty     ::init();
	Gui::ViewProviderFurnitureMaterialProperty   ::init();
	Gui::ViewProviderFurnitureTextureProperty    ::init();
	Gui::ViewFurniture_chair                     ::init();


	Workbench::init();


	PropertyItem                    ::init();
	PropertySeparatorItem           ::init();
	PropertyStringItem              ::init();
	PropertyFontItem                ::init();
	PropertyIntegerItem             ::init();
	PropertyIntegerConstraintItem   ::init();
	PropertyFloatItem               ::init();
	PropertyUnitItem                ::init();
	PropertyFloatConstraintItem     ::init();
	PropertyAngleItem               ::init();
	PropertyBoolItem                ::init();
	PropertyVectorItem              ::init();
	PropertyDoubleVectorItem        ::init();
	PropertyMatrixItem              ::init();
	PropertyPlacementItem           ::init();
	PropertyEnumItem                ::init();
	PropertyStringListItem          ::init();
	PropertyColorItem               ::init();
	PropertyFileItem                ::init();
	PropertyPathItem                ::init();
	PropertyTransientFileItem       ::init();
	PropertyLinkItem                ::init();

	NavigationStyle                 ::init();
	UserNavigationStyle             ::init();
	CADNavigationStyle              ::init();



}
Application* Application::Instance()
{
	return _instance;
}
CommandManager& Application::commandMananger(void)
{
	return d->commandManager;
}
void Application::runApplication()
{

	int argc = Application_App::GetARGC();
	int systemExit = 1000;
	GUIApplication mainApp(argc, Application_App::GetARGV(), systemExit);

	Application app;
	MainWindow w;
	QString nnn = mainApp.applicationName();
	w.setWindowTitle("furnitureDemo");
	mainApp.setActiveWindow(&w);

    app.activateWorkbench("std_workbench");
     w.loadWindowSettings();
	mainApp.exec();

  
}

Document_Gui* Application::activeDocument()const
{
  return d->activeDocument;
}

void Application::slotNewDocument(const Document_App& doc)
{
	Document_Gui* pDoc = new Document_Gui(const_cast<Document_App*>(&doc),this);
	d->documents[&doc] = pDoc;
	pDoc->signalNewObject.connect(boost::BOOST_BIND(&Application::slotNewObject,this,_1));

	signalNewDocument(*pDoc);
	pDoc->createView("view3DIv");


	
	qApp->processEvents();
}
void Application::initApplication()
{
    initTypes();
	init_resources();
}
void Application::init_resources()
{
	Q_INIT_RESOURCE(furniture);
}

#include "DocumentObject.h"
void Application::createStandardOperations()
{
   CreateStdCommands();
   CreateViewCommands();
}
void Application::viewActivated(ViewWindow* pcView)
{
	signalActivateView(pcView);
	//if(!pcView->isPassive())
	setActiveDocument(pcView->getGuiDocument());
}
void Application::setActiveDocument(Document_Gui* pcDocument)
{
     d->activeDocument = pcDocument;
}
bool Application::activateWorkbench(const char* name)
{
	return WorkbenchManager::instance()->activate(name);
}

void Application::slotNewObject(const Gui::ViewProvider& vp)
 {
 	this->signalNewObject(vp);
 }
void Application::tryClose(QCloseEvent* e)
{

}

void Application::setupContextMenu(const char* recipient,MenuItem* items)const
{
	Workbench* actWb = WorkbenchManager::instance()->active();
	if(actWb)
	actWb->setupContextMenu(recipient,items);
}

void Application::detachView(BaseView* pcView)
{

}
void Application::attachView(BaseView* pcView)
{

}

void Application::importEntity()
{
    
}
Document_Gui* Application::getDocument(const char* name)const
{
	Document_App* pdoc = GetApplication().getDocument(name);
	std::map<const Document_App*,Document_Gui*>::const_iterator it = d->documents.find(pdoc);
	if(it != d->documents.end())
		return it->second;
	else
		return NULL;
}
Document_Gui* Application::getDocument(const Document_App* pDoc)const
{
	std::map<const Document_App*,Document_Gui*>::const_iterator it = d->documents.find(pDoc);
	if(it != d->documents.end())
		return it->second;
	else
		 return NULL;
}

